home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dvi2ps
/
dvi-to-ps
/
gf.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-01
|
18KB
|
678 lines
#ifndef USEPXL
/* modified by Peter Damron 1987 University of Washington */
/*---------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] = "$Header: gf.c,v 2.0 88/06/07 15:02:50 peterd Rel2 $";
#endif lint
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include "gf.h"
/*---------------------------------------------------------------------*/
/* This file contains routines for reading character descriptions from
GF files (the output of Metafont). The following functions are defined:
gf_gettochar() finds the next character, returns its code (reduced modulo
256 if necessary), and sets global variables gf_min_m, gf_max_m,
gf_min_n, gf_max_n. A result of -1 indicates that there are no
more characters and the postamble has been found.
gf_readbits() After a character is found, this routine fills array gf_bits[]
with the character image. The image is represented in
Postscript format: the bits are packed into bytes
(most significant bit first), and the bytes scan the image
left-to-right, bottom-to-top.
Set globals gf_num_cols, gf_num_rows, gf_x_offset, gf_y_offset
(the latter give the offset of the origin from the upper
bottom corner of the image, up being a positive gf_y_offset).
gf_readpost() After the postamble is found, this routine reads it and
sets the remaining global variables declared below.
gf_seekpost() rapidly finds the postamble by random accessing the file.
gf_seekchar(c) uses fseek() to find a character with code c (modulo 256),
returning a nonzero result if successful. Global variables
are set as they are by gf_gettochar. GF files may contain
many characters with the same code, in which case subsequent
calls to gf_seekchar(c) with the same c will find the other
versions. This routine should only be called after gf_readpost().
No random access is attempted if gf_seekpost() and gf_seekchar() are not used.
*/
/*---------------------------------------------------------------------*/
/* use macros versus functions */
#define MACROS 1
#ifndef TRUE
#define FALSE 0
#define TRUE 1
#endif TRUE
/*---------------------------------------------------------------------*/
int gf_min_m; /* min horz bounding box for character */
int gf_max_m; /* max horz bounding box for character */
int gf_min_n; /* min vert bounding box for character */
int gf_max_n; /* max vert bounding box for character */
int32 gf_charfam; /* high order bytes of character code */
int gf_cur_char; /* current character - for error messages */
/*---------------------------------------------------------------------*/
/* these variables initialized by gf_readpost() */
int gf_font_min_m; /* min horz overall bounds of this font */
int gf_font_max_m; /* max horz overall bounds of this font */
int gf_font_min_n; /* min vert overall bounds of this font */
int gf_font_max_n; /* max vert overall bounds of this font */
int32 designsize; /* font size in points scaled by 1<<20 */
int32 gf_checksum; /* should match TFM file and DVI file */
int32 gf_hppp; /* horizontal and vertical pixels/point scaled 1<<16 */
int32 gf_vppp; /* horizontal and vertical pixels/point scaled 1<<16 */
int gf_char_wd[MAXCHARS]; /* character width in pixels, rounded if necessary */
int32 gf_tfm_wd[MAXCHARS]; /* width as a fraction of designsize scaled 1<<20 */
char gf_char_exists[MAXCHARS]; /* nonzero indicates presence of a char_loc */
int gf_bc; /* first nonzero gf_char_exists entries */
int gf_ec; /* last nonzero gf_char_exists entries */
int32 gf_char_pointer[MAXCHARS]; /* used by gf_seekchar() */
int32 gf_backpointer; /* set by gf_gettochar() for use by gf_seekchar() */
/*---------------------------------------------------------------------*/
#ifndef MACROS
void gf_beginc(); /* prepare to paint white at (gf_min_m,gf_max_n) */
void gf_paint(); /* paint d pixels and switch colors */
void gf_skip(); /* finish a row and skip d rows */
void gf_endc(); /* finish the last row */
#endif not MACROS
/*---------------------------------------------------------------------*/
extern void bad_gf(); /* aborts the program if the gf file is invalid */
FILE *gf_infile = stdin; /* change this externally if necessary */
char *gf_filename = 0; /* name of the currently open font file */
/*---------------------------------------------------------------------*/
/* The following macros describe gf file format */
#define GF_paint_0 0
#define GF_last_paint 63
#define GF_paint1 64
#define GF_paint2 65
#define GF_paint3 66
#define GF_boc 67
#define GF_boc1 68
#define GF_eoc 69
#define GF_skip0 70
#define GF_skip1 71
#define GF_skip2 72
#define GF_skip3 73
#define GF_new_row_0 74
#define GF_last_new_row 238
#define GF_xxx1 239
#define GF_xxx2 240
#define GF_xxx3 241
#define GF_xxx4 242
#define GF_yyy 243
#define GF_no_op 244
#define GF_char_loc 245
#define GF_char_loc0 246
#define GF_pre 247
#define GF_post 248
#define GF_postpost 249
#define undefined_cases 250: case 251: case 252: case 253: case 254: case 255
#define GF_trailer 223
#define GF_version 131
/*---------------------------------------------------------------------*/
/* misc macros for accessing bitmap */
#define row_start(n) (&(gf_bits[(n - gf_min_n)*gf_rowbytes]))
#define m_byte(m) ((m - gf_min_m)>>3) /* byte within a row containing bit m */
#define m_bit(m) (7-(m - gf_min_m)&0x7) /* bit within byte for a given m */
/* bit m on byte boundary? */
#define m_notbyteboundary(m) ((m - gf_min_m)&0x7)
/*---------------------------------------------------------------------*/
#define BITBUFSIZE 20000
unsigned char gf_bits[BITBUFSIZE];
int gf_num_cols; /* num cols (bits) in bitmap */
int gf_num_rows; /* num rows (bits) in bitmap */
int gf_num_bytes; /* num bytes in bitmap */
int gf_x_offset; /* horz offset of bitmap */
int gf_y_offset; /* vert offset of bitmap */
int gf_rowbytes; /* num bytes/row in bitmap */
static int gf_m0; /* current horz bit number (column) */
#ifndef MACROS
static int gf_m; /* current horz bit number (column) */
static int gf_n; /* current horz bit number (row) */
static int gf_paint_switch; /* paint white or black */
static unsigned char *gf_row_ptr; /* pointer to start of current row */
#endif not MACROS
/*---------------------------------------------------------------------*/
/* All gf file input goes through the following routines */
#define getbyte() (getc(gf_infile)&0xff)
#ifdef NOTDEF
int getbyte()
{
int b;
b = getc(gf_infile) & 0xff;
printf("Getting %d\n",b);
return b;
}
#endif NOTDEF
#define skip1byte() getc(gf_infile)
int get2bytes()
{ register int ans;
ans = getbyte() << 8;
ans += getbyte();
return ans;
}
int32 get3bytes()
{ register int32 ans;
ans = getbyte() << 16;
ans += getbyte() << 8;
ans += getbyte();
return ans;
}
int32 get4bytes()
{
register int32 ans;
ans = getbyte() << 24;
ans += getbyte() << 16;
ans += getbyte() << 8;
ans += getbyte();
return ans;
}
#ifdef MACROS
#define skip_bytes(n) { \
while (n-- > 0) skip1byte(); \
}
#else not MACROS
void skip_bytes(n)
int n;
{
while (n-- > 0) skip1byte();
}
#endif MACROS
/*---------------------------------------------------------------------*/
/* In the unlikely event of a character code outside of the range 0..255,
the high order bytes are placed in the global variable gf_charfam.
If no boc command is encountered, the result is -1 and the last byte read
is guaranteed to be the post command.
*/
int gf_gettochar()
{
int32 c; /* the character code to be returned */
register int x; /* temporary */
register int len; /* temporary */
for(;;) switch(getbyte())
{
case GF_yyy: skip1byte(); /* intended to fall through 3 times */
case GF_paint3: case GF_skip3: skip1byte();
case GF_paint2: case GF_skip2: skip1byte();
case GF_paint1: case GF_skip1: skip1byte(); continue;
case GF_boc: c = get4bytes();
gf_backpointer = get4bytes();
gf_min_m = get4bytes();
gf_max_m = get4bytes();
gf_min_n = get4bytes();
gf_max_n = get4bytes();
gf_charfam = c<0 ? -((-c)>>8) : c>>8;
gf_cur_char = c&0377;
return c&0377;
case GF_boc1: c = getbyte();
gf_backpointer = -1;
x = getbyte(); /* del_m */
gf_max_m = getbyte();
gf_min_m = gf_max_m - x;
x = getbyte(); /* del_n */
gf_max_n = getbyte();
gf_min_n = gf_max_n - x;
gf_cur_char = c;
return c;
case GF_pre: if (getbyte() != GF_version) bad_gf(1);
len = getbyte();
skip_bytes(len);
continue;
case GF_xxx1:
len = getbyte();
skip_bytes(len);
continue;
case GF_xxx2:
len = get2bytes();
skip_bytes(len);
continue;
case GF_xxx3:
len = get3bytes();
skip_bytes(len);
continue;
case GF_xxx4:
len = get4bytes();
skip_bytes(len);
continue;
case GF_post: return -1;
case GF_char_loc: case GF_char_loc0: case GF_postpost: case undefined_cases:
bad_gf(2);
default: /* do nothing */;
}
}
/*---------------------------------------------------------------------*/
/* read the post-amble of a gf format font file */
void gf_readpost()
{
register int i;
register int b;
register int c;
get4bytes(); /* ignore back pointer to font-wide xxx commands */
designsize = get4bytes();
gf_checksum = get4bytes();
gf_hppp = get4bytes();
gf_vppp = get4bytes();
gf_font_min_m = get4bytes();
gf_font_max_m = get4bytes();
gf_font_min_n = get4bytes();
gf_font_max_n = get4bytes();
for(i = 0; i < MAXCHARS; i++) {
gf_char_exists[i] = FALSE;
gf_char_wd[i] = 0;
gf_tfm_wd[i] = 0;
gf_char_pointer[i] = -1;
}
gf_bc = MAXCHARS;
gf_ec = 0;
for (;;) {
b = getbyte();
c = getbyte();
if (b == GF_char_loc0) {
gf_char_wd[c] = getbyte();
} else if (b == GF_char_loc) {
gf_char_wd[c] = (get4bytes()+0100000)>>16;
get4bytes(); /* skip dy */
} else {
break;
}
gf_tfm_wd[c] = get4bytes();
gf_char_pointer[c] = get4bytes();
gf_char_exists[c] = TRUE;
if (gf_bc>c) gf_bc = c;
if (gf_ec<c) gf_ec = c;
}
gf_cur_char = -1;
}
/*---------------------------------------------------------------------*/
/* find the post-amble of a gf format font file */
void gf_seekpost()
{
int c;
fseek(gf_infile, -5L, 2); /* skip four 223's */
do {
c = getbyte();
fseek(gf_infile, -2L, 1);
} while (c == GF_trailer);
if (c != GF_version) bad_gf(5); /* check version number */
fseek(gf_infile, -3L, 1); /* back up to the pointer */
if (fseek(gf_infile, (long) get4bytes(), 0) < 0) bad_gf(6);
if (getbyte() != GF_post) bad_gf(7);
gf_cur_char = -1;
}
/*---------------------------------------------------------------------*/
/* find a character definition in a gf format font file */
int gf_seekchar(c)
int c;
{
if (c < 0 || c > MAXCHARS-1 || gf_char_pointer[c] < 0) return FALSE;
if (fseek(gf_infile, gf_char_pointer[c], 0) < 0) bad_gf(8);
if (gf_gettochar() != c) bad_gf(9);
gf_cur_char = c;
return TRUE;
}
/*---------------------------------------------------------------------*/
/* begin a character, initialize data */
#ifdef MACROS
#define gf_beginc(dummy) { \
gf_num_cols = gf_max_m - gf_min_m + 1; \
gf_num_rows = gf_max_n - gf_min_n + 1; \
gf_x_offset = -gf_min_m; \
gf_y_offset = -gf_min_n; \
gf_rowbytes = (gf_num_cols+7)/8; \
gf_num_bytes = gf_num_rows*gf_rowbytes; \
if (gf_num_bytes >= BITBUFSIZE) \
bad_gf(10); /* really, should allocate a bigger one */ \
gf_m = gf_m0 = gf_min_m; \
gf_n = gf_max_n; \
gf_row_ptr = row_start(gf_max_n); \
bzero(gf_bits, gf_num_bytes); \
gf_paint_switch = FALSE; \
}
#else not MACROS
void gf_beginc()
{
gf_num_cols = gf_max_m - gf_min_m + 1;
gf_num_rows = gf_max_n - gf_min_n + 1;
gf_x_offset = -gf_min_m;
gf_y_offset = -gf_min_n;
gf_rowbytes = (gf_num_cols+7)/8;
gf_num_bytes = gf_num_rows*gf_rowbytes;
if (gf_num_bytes >= BITBUFSIZE) {
bad_gf(10); /* really, should allocate a bigger one */
}
gf_m = gf_m0 = gf_min_m;
gf_n = gf_max_n;
gf_row_ptr = row_start(gf_max_n);
bzero(gf_bits, gf_num_bytes);
gf_paint_switch = FALSE;
}
#endif MACROS
/*---------------------------------------------------------------------*/
/* paint a portion of a row of bits into the bitmap */
/* this is a decoding of a run length encoding of a bitmap */
/* d is the number of bits (run length) to encode */
/* gf_paint_switch is a true for one-bits and false for zero bits */
/* this is the old version */
#ifdef NOTDEF
void gf_paint(d)
register int d;
{
if (d>0) {
if (gf_paint_switch) {
while (d-- >0) {
gf_row_ptr[m_byte(gf_m)] |= 1<<m_bit(gf_m);
gf_m++;
}
} else {
gf_m += d;
}
}
gf_paint_switch ^= 1;
}
#endif NOTDEF
/*---------------------------------------------------------------------*/
/* paint a portion of a row of bits into the bitmap */
/* this is a decoding of a run length encoding of a bitmap */
/* d is the number of bits (run length) to encode */
/* gf_paint_switch is a true for one-bits and false for zero bits */
/* row-ptr is a pointer to the beginning of this row */
/* gf_m is the distance (bits) from the beginning of the row (output bitmap) */
#ifdef MACROS
#define gf_paint(len) { \
if (len > 0) { \
if (gf_paint_switch) { \
/* paint white (==1) */ \
/* first fill in the first partial byte */ \
while ((len > 0) && m_notbyteboundary(gf_m)) { \
gf_row_ptr[m_byte(gf_m)] |= 1 << m_bit(gf_m); \
gf_m += 1; \
len -= 1; \
} \
/* now fill in the whole bytes */ \
while (len > 0) { \
/* note (gf_m & 0x7 == 0) */ \
/* this is an even byte boundary */ \
/* so we know what to put into this byte */ \
if (len >= 8) { \
/* this byte is full */ \
gf_row_ptr[m_byte(gf_m)] = 0xFF; \
gf_m += 8; \
len -= 8; \
} else { \
/* this byte is partial */ \
/* len&7 == len div 8 */ \
gf_row_ptr[m_byte(gf_m)] = (0xFF << (8-len)) & 0xFF; \
gf_m += len; \
len = 0; \
} \
} \
gf_paint_switch = FALSE; \
} else { \
/* paint black (==0) is easy */ \
gf_m += len; \
gf_paint_switch = TRUE; \
} \
} else { \
/* len <= 0 */ \
if (len < 0) { \
Warning("internal - unexpected value in gf_paint %d\n",len); \
} \
gf_paint_switch = !gf_paint_switch; \
} \
}
#else not MACROS
void gf_paint(len)
register int len;
{
/* why was I called? */
if (len <= 0) {
if (len < 0) {
Warning("internal - unexpected value in gf_paint %d\n",len);
}
gf_paint_switch = !gf_paint_switch;
return;
}
/* paint black (==0) is easy */
if (!gf_paint_switch) {
gf_m += len;
gf_paint_switch = TRUE;
return;
}
/* paint white (==1) */
/* first fill in the first partial byte */
while ((len > 0) && m_notbyteboundary(gf_m)) {
gf_row_ptr[m_byte(gf_m)] |= 1 << m_bit(gf_m);
gf_m += 1;
len -= 1;
}
/* now fill in the whole bytes */
while (len > 0) {
/* note (gf_m & 0x7 == 0) */
/* this is an even byte boundary */
/* so we know what to put into this byte */
if (len >= 8) {
/* this byte is full */
gf_row_ptr[m_byte(gf_m)] = 0xFF;
gf_m += 8;
len -= 8;
} else {
/* this byte is partial */
/* len&7 == len div 8 */
gf_row_ptr[m_byte(gf_m)] = (0xFF << (8-len)) & 0xFF;
gf_m += len;
len = 0;
}
}
gf_paint_switch = FALSE;
}
#endif MACROS
/*---------------------------------------------------------------------*/
/* skip to the next row of bits */
#ifdef MACROS
#define gf_skip(d) { \
gf_n -= d+1; \
gf_m = gf_m0; \
gf_row_ptr = row_start(gf_n); \
gf_paint_switch = FALSE; \
}
#else not MACROS
void gf_skip(d)
int d;
{
gf_n -= d+1;
gf_m = gf_m0;
gf_row_ptr = row_start(gf_n);
gf_paint_switch = FALSE;
}
#endif MACROS
/*---------------------------------------------------------------------*/
/* end of character */
#ifdef MACROS
#define gf_endc(dummy)
#else not MACROS
void gf_endc() { /* do nothing */ }
#endif MACROS
/*---------------------------------------------------------------------*/
/* gf_readbits reads a raster description from the gf file and uses the external
routines to actually process the raster information.
*/
void gf_readbits()
{
/* register unsigned char byt; */
register int byt;
register int len;
#ifdef MACROS
register unsigned char *gf_row_ptr; /* start of current row */
register int gf_m; /* current horz bit number (column) */
register int gf_paint_switch; /* paint white or black */
register int gf_n; /* current horz bit number (row) */
#endif MACROS
gf_beginc();
for (;;) {
byt = getbyte();
if (byt <= GF_last_paint) {
len = byt - GF_paint_0;
gf_paint(len);
}
if (byt < GF_new_row_0) {
switch(byt) {
case GF_paint1:
len = getbyte();
gf_paint(len);
continue;
case GF_paint2:
len = get2bytes();
gf_paint(len);
continue;
case GF_paint3:
len = get3bytes();
gf_paint(len);
continue;
case GF_boc:
case GF_boc1:
bad_gf(3);
case GF_eoc:
goto finish;
case GF_skip0:
gf_skip(0);
continue;
case GF_skip1:
len = getbyte();
gf_skip(len);
continue;
case GF_skip2:
len = get2bytes();
gf_skip(len);
continue;
case GF_skip3:
len = get3bytes();
gf_skip(len);
continue;
}
} else if (byt <= GF_last_new_row) {
gf_skip(0);
len = byt - GF_new_row_0;
gf_paint(len);
} else {
switch(byt) {
case GF_xxx1:
len = getbyte();
skip_bytes(len);
continue;
case GF_xxx2:
len = get2bytes();
skip_bytes(len);
continue;
case GF_xxx3:
len = get3bytes();
skip_bytes(len);
continue;
case GF_xxx4:
len = get4bytes();
skip_bytes(len);
continue;
case GF_yyy:
get4bytes();
continue;
case GF_no_op:
continue;
default:
bad_gf(4);
}
}
}
finish: gf_endc();
}
/*---------------------------------------------------------------------*/
/* report errors */
void bad_gf(n)
int n;
{
Fatal("bad gf font file %s\n char %d offset %d case %d\n",
gf_filename,gf_cur_char,ftell(gf_infile),n);
}
/*---------------------------------------------------------------------*/
#endif USEPXL